package org.example.security.autoconfiguration;

import org.example.security.component.RestAuthenticationEntryPoint;
import org.example.security.component.RestfulAccessDeniedHandler;
import org.example.security.config.SecurityConfiguration;
import org.example.security.filter.DefaultJwtAuthenticationTokenFilter;
import org.example.security.filter.JwtAuthenticationTokenFilter;
import org.example.security.util.JwtTokenUtil;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.AccessDeniedHandler;

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableConfigurationProperties({SecurityProperties.class, SecurityProperties.JWTProperties.class})
public class SecurityAutoConfiguration {

    private SecurityProperties securityProperties;

    /**
     * 构造注入属性
     * @param securityProperties 属性
     */
    public SecurityAutoConfiguration(SecurityProperties securityProperties) {
        this.securityProperties = securityProperties;
    }

    /**
     * 安全配置类
     * @return WebSecurityConfigurerAdapter
     */
    @Bean
    public WebSecurityConfigurerAdapter securityConfigurerAdapter() {
        return new SecurityConfiguration(securityProperties,jwtAuthenticationTokenFilter(),
                authenticationEntryPoint(),accessDeniedHandler());
    }

    /**
     * 认证管理器
     * @return AuthenticationManager
     * @throws Exception 异常
     */
    @Bean
    public AuthenticationManager authenticationManager() throws Exception {
        return securityConfigurerAdapter().authenticationManagerBean();
    }

    @Bean
    @ConditionalOnMissingBean(JwtAuthenticationTokenFilter.class)
    public JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter() {
        return new DefaultJwtAuthenticationTokenFilter(securityProperties,jwtTokenUtil());
    }

    @Bean
    @ConditionalOnMissingBean(PasswordEncoder.class)
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    @ConditionalOnMissingBean(AuthenticationEntryPoint.class)
    public AuthenticationEntryPoint authenticationEntryPoint() {
        return new RestAuthenticationEntryPoint();
    }

    @Bean
    @ConditionalOnMissingBean(AccessDeniedHandler.class)
    public AccessDeniedHandler accessDeniedHandler() {
        return new RestfulAccessDeniedHandler();
    }

    @Bean
    public JwtTokenUtil jwtTokenUtil() {
        return new JwtTokenUtil(securityProperties);
    }
}
